package com.corpgovernment.common.utils;

import com.corpgovernment.common.dto.CheckRepeatDto;
import com.google.common.collect.Lists;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Pinyin4jUtil {


    /**
     * 字符串获取汉字全拼，非汉字则直接不处理直接拼接
     *
     * @param chinese
     * @return
     * @throws Exception
     */
    public static Map<Character, List<String>> getFullSpell(String chinese) throws Exception {
        HashMap<Character, List<String>> pinyinMap = new HashMap();
        char[] arr = chinese.toCharArray();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (int i = 0; i < arr.length; i++) {
            if (String.valueOf(arr[i]).matches("[\\u4E00-\\u9FA5]+")) { //中文处理变为拼音
                pinyinMap.put(arr[i], Arrays.asList(PinyinHelper.toHanyuPinyinStringArray(arr[i], defaultFormat)));
            } else {
                pinyinMap.put(arr[i], Lists.newArrayList(String.valueOf(arr[i])));
            }
        }
        return pinyinMap;
    }


    public static ArrayList<String> getFullSpell(Character word) throws Exception {
        if (word == null) {
            return null;
        }
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        if (String.valueOf(word).matches("[\\u4E00-\\u9FA5]+")) { //中文处理变为拼音
            return Lists.newArrayList(PinyinHelper.toHanyuPinyinStringArray(word.charValue(), defaultFormat));
        } else {
            return Lists.newArrayList(String.valueOf(word));
        }
    }

    /**
     * 判断字符是否重复（中文装换成全拼）拼音包含多音字，只要其中有一个音相同则判断是相同
     *
     * @return true有重复，false没有重合
     */
    public static CheckRepeatDto CheckRepeat(List<String> chineseList) throws Exception {
        CheckRepeatDto checkRepeatDto = new CheckRepeatDto();
        checkRepeatDto.setCheck(Boolean.FALSE);
        if (!CollectionUtils.isEmpty(chineseList)) {

            //如果自由一个人则直接返回
            int size = chineseList.size();
            if (size == 1) {
                checkRepeatDto.setCheck(Boolean.FALSE);
                return checkRepeatDto;
            }
            HashMap<Character, ArrayList<String>> pinYinCache = new HashMap<>();
            Integer count = 0;
            Boolean hasEqual = Boolean.FALSE;
            for (int i = 0; i < size; i++) {
                //判断这个词有没有相同音，记录个数标识
                Boolean countFlag = Boolean.FALSE;
                for (int j = i + 1; j < size; j++) {
                    if (i == j) {
                        continue;
                    }
                    String firstWord = chineseList.get(i);
                    String secondWord = chineseList.get(j);
                    //长度不一样则认为这两个名字不一样
                    if (firstWord.length() != secondWord.length()) {
                        continue;
                    }
                    char[] firstChars = firstWord.toCharArray();
                    char[] secondChars = secondWord.toCharArray();
                    //判断每一个字是否拼音有一样的
                    Boolean isEqual = Boolean.FALSE;
                    for (int k = 0; k < firstChars.length; k++) {
                        //如果字符一样不去判断拼音
                        if (firstChars[k] == secondChars[k]) {
                            isEqual = Boolean.TRUE;
                            continue;
                        }
                        //字符不一样则判断拼音
                        ArrayList<String> firstFullSpell = getPinYin(pinYinCache, firstChars[k]);
                        ArrayList<String> secondFullSpell = getPinYin(pinYinCache, secondChars[k]);
                        //有交集则此字符存在同音
                        if (containsOne(firstFullSpell, secondFullSpell)) {
                            isEqual = Boolean.TRUE;
                        } else {
                            isEqual = Boolean.FALSE;

                        }
                    }
                    //循环完整个名字isEqual是true则这个两个名字拼音存在相同
                    if (isEqual) {
                        countFlag = Boolean.TRUE;
                        hasEqual = Boolean.TRUE;
                    }
                }
                //计算个数
                if (countFlag) {
                    count++;
                }
            }
            checkRepeatDto.setCheck(hasEqual);
            if (hasEqual) {
                checkRepeatDto.setCount(count + 1);
            }
        }
        return checkRepeatDto;
    }

    /**
     * 两个列表，判断是否A中有B的元素
     *
     * @param firstFullSpell
     * @param secondFullSpell
     * @return
     */
    private static Boolean containsOne(ArrayList<String> firstFullSpell, ArrayList<String> secondFullSpell) {
        for (String o : firstFullSpell) {
            if (secondFullSpell.contains(o)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 获取拼音缓存数据
     *
     * @param pinYinCache
     * @param character
     * @return
     * @throws Exception
     */
    private static ArrayList<String> getPinYin(HashMap<Character, ArrayList<String>> pinYinCache, Character character) throws Exception {
        //存在缓存中这取缓存数据
        if (pinYinCache.containsKey(character)) {
            return pinYinCache.get(character);
        }
        //没有则执行方法设置缓存
        ArrayList<String> fullSpell = getFullSpell(character);
        if (CollectionUtils.isEmpty(fullSpell)) {
            return Lists.newArrayList();
        }
        pinYinCache.put(character, fullSpell);
        return fullSpell;
    }


    public static CheckRepeatDto checkRepeatNew(List<String> passengerNameList) throws Exception {
        CheckRepeatDto checkRepeatDto = new CheckRepeatDto();
        checkRepeatDto.setCheck(Boolean.FALSE);
        List<List<String>> allNameList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(passengerNameList)) {
            for (String passengerName : passengerNameList) {
                if (StringUtils.isNotBlank(passengerName)) {
                    char[] chars = passengerName.toCharArray();
                    //当前名字的各个字的组合
                    List<List<String>> list = new ArrayList<>(chars.length);
                    for (int i = 0; i < chars.length; i++) {
                        //当前汉字的所有拼音组合
                        List<String> pinyinList = Pinyin4jUtil.getFullSpell(chars[i]);
                        list.add(pinyinList);
                    }
                    List<List<String>> resultList = new ArrayList<>();
                    List<String> currentList = new ArrayList<>();
                    descartes(list, resultList, 0, currentList);
                    List<String> pxName = new ArrayList<>();
                    for (List<String> ll : resultList) {
                        StringBuilder sb = new StringBuilder();
                        for (String s : ll) {
                            sb.append(s).append("|");
                        }
                        pxName.add(sb.toString());
                    }
                    allNameList.add(pxName);
                }
            }

            //循环allNameList [[zhangsan ,lisi] [lisi,lisa] [wangwu,wangba]]
            int count = 0;
            for (int a = 0; a < allNameList.size(); a++) {
                //[zhangsan ,lisi]
                List<String> aList = allNameList.get(a);
                //构建其余元素的集合
                List<String> cList = new ArrayList<>(allNameList.size() -1);
                for (int c = 0; c< allNameList.size(); c++) {
                    if(c !=a ){
                        cList.addAll(allNameList.get(c));
                    }
                }
                //[lisi,lisa,wangwu,wangba]
                for (int b = 0; b < aList.size(); b++) {
                    //zhangsan
                    if(cList.contains(aList.get(b))){
                        count ++;
                        break;
                    }
                }
            }
            if(count > 0){
                checkRepeatDto.setCheck(true);
                checkRepeatDto.setCount(count);
            }
        }
        return checkRepeatDto;
    }

    /**
     * Discription: 笛卡尔乘积算法
     * 把一个List{[1,2],[A,B],[a,b]} 转化成
     * List{[1,A,a],[1,A,b],[1,B,a],[1,B,b],[2,A,a],[2,A,b],[2,B,a],[2,B,b]} 数组输出
     *
     * @param dimensionValue 原List
     * @param result         通过乘积转化后的数组
     * @param layer          中间参数
     * @param currentList    中间参数
     */
    public static void descartes(List<List<String>> dimensionValue, List<List<String>> result, int layer, List<String> currentList) {
        if (layer < dimensionValue.size() - 1) {
            if (dimensionValue.get(layer).size() == 0) {
                descartes(dimensionValue, result, layer + 1, currentList);
            } else {
                for (int i = 0; i < dimensionValue.get(layer).size(); i++) {
                    List<String> list = new ArrayList<String>(currentList);
                    list.add(dimensionValue.get(layer).get(i));
                    descartes(dimensionValue, result, layer + 1, list);
                }
            }
        } else if (layer == dimensionValue.size() - 1) {
            if (dimensionValue.get(layer).size() == 0) {
                result.add(currentList);
            } else {
                for (int i = 0; i < dimensionValue.get(layer).size(); i++) {
                    List<String> list = new ArrayList<String>(currentList);
                    list.add(dimensionValue.get(layer).get(i));
                    result.add(list);
                }
            }
        }
    }

}